package cHelper

import (
	"fmt"
	"runtime"
	"strings"
)

func CallerFuncName() string {
	var name string
	pc, _, _, _ := runtime.Caller(1)
	full := runtime.FuncForPC(pc).Name()
	names := strings.Split(full, ".")

	if len(names) > 0 {
		name = names[len(names)-1]
	}

	return name
}

func Recover() func() {
	return func() {
		if r := recover(); r != nil {
			const size = 64 << 10
			buf := make([]byte, size)
			buf = buf[:runtime.Stack(buf, false)]
			err, ok := r.(error)
			if !ok {
				err = fmt.Errorf("%v", r)
			}
			fmt.Println(err, "panic", "stack", "\n", string(buf))
		}
	}
}

func GetCallerFileAndLine(skip int, includes, excludes []string) string {
	pcs := make([]uintptr, 99)
	total := runtime.Callers(skip, pcs)

	result := ""
	include, exclude := true, false

	for i := 0; i < total; i++ {
		_, file, line, ok := runtime.Caller(skip + i)
		if i == 0 {
			result = fmt.Sprintf("%s:%d", file, line)
		}
		if ok {
			if len(includes) > 0 {
				include = false
				for _, item := range includes {
					if strings.Contains(file, item) {
						include = true
						break
					}
				}
			}
			if len(excludes) > 0 {
				exclude = false
				for _, item := range excludes {
					if strings.Contains(file, item) {
						exclude = true
						break
					}
				}
			}
			if include && !exclude {
				return fmt.Sprintf("%s:%d", file, line)
			}
		}
	}

	return result
}

func GetBuildPath(names ...string) string {
	name := "server/main.go"
	if len(names) > 0 {
		name = strings.Join(names, "/")
	}

	pcs := make([]uintptr, 99)
	l := runtime.Callers(0, pcs)

	for i := l; i > 0; i-- {
		_, file, _, ok := runtime.Caller(i)
		if ok && strings.Contains(file, name) {
			return strings.TrimRight(file, name)

		}
	}

	return ""
}
